package com.gitee.zihaolicn;


import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {

    // ForkJoin任务，用于递归搜索目录
    static class FileSearchTask extends RecursiveTask<List<Path>> {
        private static final int THRESHOLD = 50; // 文件数量阈值，决定是否继续分割任务
        private final Path directory;
        private final PathMatcher matcher;

        public FileSearchTask(Path directory, PathMatcher matcher) {
            this.directory = directory;
            this.matcher = matcher;
        }

        @Override
        protected List<Path> compute() {
            System.out.println("handle "+ directory.toString());
            List<Path> results = new ArrayList<>();
            List<FileSearchTask> subTasks = new ArrayList<>();

            try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
                List<Path> entries = new ArrayList<>();
                for (Path entry : stream) {
                    entries.add(entry);
                }

                // 如果目录中的条目较少，直接处理
                if (entries.size() <= THRESHOLD) {
                    for (Path entry : entries) {
                        if (Files.isDirectory(entry)) {
                            // 对子目录创建新任务
                            FileSearchTask subTask = new FileSearchTask(entry, matcher);
                            subTask.fork(); // 异步执行
                            subTasks.add(subTask);
                        } else if (Files.isRegularFile(entry) && matcher.matches(entry)) {
                            results.add(entry);
                        }
                    }
                } else {
                    // 如果条目较多，分割任务
                    int mid = entries.size() / 2;
                    List<Path> leftEntries = entries.subList(0, mid);
                    List<Path> rightEntries = entries.subList(mid, entries.size());

                    // 处理左半部分
                    for (Path entry : leftEntries) {
                        if (Files.isDirectory(entry)) {
                            FileSearchTask subTask = new FileSearchTask(entry, matcher);
                            subTask.fork();
                            subTasks.add(subTask);
                        } else if (Files.isRegularFile(entry) && matcher.matches(entry)) {
                            results.add(entry);
                        }
                    }

                    // 处理右半部分
                    for (Path entry : rightEntries) {
                        if (Files.isDirectory(entry)) {
                            FileSearchTask subTask = new FileSearchTask(entry, matcher);
                            subTask.fork();
                            subTasks.add(subTask);
                        } else if (Files.isRegularFile(entry) && matcher.matches(entry)) {
                            results.add(entry);
                        }
                    }
                }

                // 收集所有子任务的结果
                for (FileSearchTask task : subTasks) {
                    results.addAll(task.join());
                }

            } catch (IOException e) {
                // 处理无法访问的目录，记录错误但继续搜索
                System.err.println("无法访问目录: " + directory + " - " + e.getMessage());
            }

            return results;
        }
    }

    // 使用Java 8+ Stream API的并行实现（备选方案）
    public static class StreamBasedSearcher {

        public static List<Path> searchClassFiles(String rootPath) throws IOException {
            Path root = Paths.get(rootPath);

            if (!Files.exists(root) || !Files.isDirectory(root)) {
                throw new IllegalArgumentException("指定的路径不存在或不是目录: " + rootPath);
            }

            try (Stream<Path> paths = Files.walk(root)) {
                return paths.parallel() // 使用并行流
                        .filter(Files::isRegularFile)
                        .filter(path -> path.toString().toLowerCase().endsWith("pdf"))
                        .collect(Collectors.toList());
            }
        }
    }

    // 主搜索方法
    public static List<Path> searchClassFiles(String rootPath) {
        Path root = Paths.get(rootPath);

        // 验证路径
        if (!Files.exists(root) || !Files.isDirectory(root)) {
            throw new IllegalArgumentException("指定的路径不存在或不是目录: " + rootPath);
        }

        // 创建路径匹配器
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.pdf");

        // 创建ForkJoinPool，使用所有可用的处理器
        ForkJoinPool pool = new ForkJoinPool();

        try {
            // 创建并执行根任务
            FileSearchTask rootTask = new FileSearchTask(root, matcher);
            return pool.invoke(rootTask);
        } finally {
            pool.shutdown();
        }
    }

    // 带有自定义线程池大小的搜索方法
    public static List<Path> searchClassFiles(String rootPath, int parallelism) {
        Path root = Paths.get(rootPath);

        if (!Files.exists(root) || !Files.isDirectory(root)) {
            throw new IllegalArgumentException("指定的路径不存在或不是目录: " + rootPath);
        }

        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("*.pdf");

        // 使用自定义的并行度
        ForkJoinPool pool = new ForkJoinPool(parallelism);

        try {
            FileSearchTask rootTask = new FileSearchTask(root, matcher);
            return pool.invoke(rootTask);
        } finally {
            pool.shutdown();
        }
    }

    // 示例用法和性能测试
    public static void main(String[] args) {
        /*if (args.length < 1) {
            System.out.println("用法: java ParallelFileSearcher <根目录路径>");
            return;
        }*/

        //String rootPath = args[0];
        String rootPath = "E:\\下载";
        System.out.println(rootPath);
        try {
            // 测试ForkJoin实现
            long startTime = System.currentTimeMillis();
            List<Path> classFiles = searchClassFiles(rootPath);
            long endTime = System.currentTimeMillis();

            System.out.println("=== ForkJoin实现 ===");
            System.out.println("找到 " + classFiles.size() + " 个.class文件");
            System.out.println("搜索耗时: " + (endTime - startTime) + " ms");

            // 显示前10个结果
            System.out.println("\n前10个结果:");
            classFiles.stream()
                    .limit(10)
                    .forEach(path -> System.out.println("  " + path));

            // 测试Stream API实现
            startTime = System.currentTimeMillis();
            List<Path> streamResults = StreamBasedSearcher.searchClassFiles(rootPath);
            endTime = System.currentTimeMillis();

            System.out.println("\n=== Stream API实现 ===");
            System.out.println("找到 " + streamResults.size() + " 个.class文件");
            System.out.println("搜索耗时: " + (endTime - startTime) + " ms");

            // 性能对比
            System.out.println("\n=== 性能信息 ===");
            System.out.println("可用处理器数: " + Runtime.getRuntime().availableProcessors());
            System.out.println("最大内存: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + " MB");

        } catch (Exception e) {
            System.err.println("搜索过程中发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
